/////////////////////////////////////////////////////////////////////////////////
// odoDB.c  C Test file for neptuner                                        //
// Copyright 2009, Ocodoco Unlimited                                           //
/////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////
/**
 * \file    odoDB.c
 * \author  Sonofdelphi
 * \brief   odo test DB Implementation.
 */
/////////////////////////////////////////////////////////////////////////////////

#include "odoDB.h"
#include "odoDBQ.h"

//////////////////////////
/* **********************/
/* DBCOL PROPERTIES  */
/* **********************/
//////////////////////////

unsigned char gnAtomRecordID;
unsigned char gnBConfupRecordID;
unsigned char gnRollBConf;

bool gbXSessionEnabled;
bool gbXSessionLocked;
bool gbXSessionRetry;
bool gbXSessionMaster;

//////////////////////////
/* **********************/
/* DBCOL MEMBERS     */
/* **********************/
//////////////////////////

DBRecord gxRecordTemp;
DBRecord gxRecordFlow;
DBRecord gxAtomRecord;
DBRecord gxRecordBConfupd;

void 
odoDBDelegateBConfupRecord
    (
    void
    )
    {
    int nQueryStat;

	nQueryStat = UNDEF;

    nQueryStat = DBSendFlowRecord(eForce);
    ASSERT_SUCCESS(nQueryStat);

    gnBConfupRecordID = Increment(gnBConfupRecordID,
                                    (DB_MAX_Record_ID+1));

    nQueryStat = DBMacroQCommit(&gxRecordBConfupd);
    ASSERT_SUCCESS(nQueryStat);

    return;
    }

void 
odoDBDelegateValidConf
    (
    void
    )
    {
    int nQueryStat;
    bool bIsQEmpty;

	nQueryStat = UNDEF;
    bIsQEmpty = TRUE;

    nQueryStat = odoDBRetryConfirmRetry();
    ASSERT_SUCCESS(nQueryStat);
    
    nQueryStat = odoDBTimeoutCommit(FALSE);
    ASSERT_SUCCESS(nQueryStat);
    
    gnAtomRecordID = Increment(gnAtomRecordID,
                                        (DB_MAX_Record_ID + 1));

    nQueryStat = DBAtomQIsEmpty(&bIsQEmpty);
    ASSERT_SUCCESS(nQueryStat);

    if (FALSE == bIsQEmpty)
        {
        nQueryStat = odoDBMacroCommit(TRUE);
        ASSERT_SUCCESS(nQueryStat);
        }

    gbXSessionLocked = FALSE;
	gnRollBConf = 0;

    return;
    }

void 
odoDBDelegateInvalidRecord
    (
    void
    )
    {
    
    return;
    }

void odoDBDelegateCancel
    (
    void
    )
    {
    
    return;
    }

void 
odoDBDelegateSessionRecord
    (
    void
    )
    {
    int nQueryStat;

	nQueryStat = UNDEF;

	if(TRUE == gbXSessionMaster)
		{
		nQueryStat = odoDBRetryConfirmRetry();
		ASSERT_SUCCESS(nQueryStat);

		gbXSessionMaster = FALSE;

		DBSendFlowRecord(eSession);
		}

    return;
    }

void 
odoDBInit
    (
    void
    )
    {
    int nQueryStat;

	nQueryStat = UNDEF;

    nQueryStat = DBQSetup();
    ASSERT_SUCCESS(nQueryStat);

#ifdef XSession_1
	gbXSessionMaster = TRUE;
#else
	gbXSessionMaster = FALSE;
#endif
	
    gnAtomRecordID = 0;
    gnBConfupRecordID = 0;
    gnRollBConf = 0;

    gbXSessionLocked = FALSE;
    gbXSessionRetry= FALSE;
    gbXSessionEnabled = TRUE;

	return;
    }

void 
odoDBRecordProcess
    (
    void
    )
    {
    DBRecordType		eRecordType;
    unsigned short      u16RecordSize;
    unsigned short		u16Size;
    void			nQueryStat;
    unsigned char		nTotal;
    bool                bIsValidRecord;
    bool                bIsQEmpty;

	nQueryStat = UNDEF;
	bIsValidRecord = FALSE;
	bIsQEmpty = TRUE;

    ASSERT(gbXSessionEnabled);

    nQueryStat = DBBConfupQPop( &gxRecordBConfupd);
    ASSERT_SUCCESS(nQueryStat);

    nQueryStat = DBBConfupQIsEmpty(&bIsQEmpty);
    ASSERT_SUCCESS(nQueryStat);

    if (FALSE == bIsQEmpty)
        {
        nQueryStat = odoDBRecordCommit(TRUE);
        ASSERT_SUCCESS(nQueryStat);
        }

    nQueryStat = DBRecordBufferSize(&gxRecordBConfupd,
    						&u16Size /* Check */
    						);
    ASSERT_SUCCESS(nQueryStat);

    nQueryStat = DBRecordIsValid( (unsigned char*)&gxRecordBConfupd,
                          u16Size, /* Check */
                          &bIsValidRecord );
    ASSERT_SUCCESS(nQueryStat);

    if ( FALSE == bIsValidRecord )
        {
        nQueryStat = odoDBDelegateInvalidRecord();
        ASSERT_SUCCESS(nQueryStat);
        return;
        }

    nQueryStat = DBRecordBufferSize(&gxRecordBConfupd, &u16RecordSize);
    ASSERT_SUCCESS(nQueryStat);

    nQueryStat = DBRecordBufferStructize(&gxRecordBConfupd, u16RecordSize);
    ASSERT_SUCCESS(nQueryStat);

    nQueryStat = DBRecordFlowCharType(gxRecordBConfupd.nRecordFlow,
                                    &eRecordType);
    ASSERT_SUCCESS(nQueryStat);

	if(TRUE == gbXSessionMaster)
		{
		if(eSession !=eRecordType)
			{
			return UNDEF;
			}
		}

    if ( eMacro != eRecordType)
        {
        nQueryStat = DBFlowRecordSave(
                        gxRecordBConfupd.nRecordFlow);
        ASSERT_SUCCESS(nQueryStat);
        return;
        }

    nQueryStat = DBRecordFlowCharTotal(gxRecordBConfupd.nRecordFlow,
                                   &nTotal);
    ASSERT_SUCCESS(nQueryStat);

    if (nTotal == Predecessor(gnBConfupRecordID,
                                        (DB_MAX_Record_ID + 1)))
        {
        nQueryStat =DBSendFlowRecord(eForcePrev);
        ASSERT_SUCCESS(nQueryStat);

		return;
        }

    if ( gnBConfupRecordID != nTotal )
        /* Is an UnBConfup Record */
        {
        nQueryStat = odoDBDelegateUnBConfupRecord();
        ASSERT_SUCCESS(nQueryStat);

        return;
        }

    if ( gnBConfupRecordID == nTotal)
        {
        nQueryStat = odoDBDelegateBConfupRecord();
        ASSERT_SUCCESS(nQueryStat);
        return;
        }

    return UNDEF;
    }

void 
odoDBMacroSendRecord
    (
    void
    )
    {
    unsigned short u16RecordSize;
    int nQueryStat;

	nQueryStat = UNDEF;

    ASSERT(gbXSessionEnabled);

    if (FALSE == gbXSessionRetry)
        {
        if (FALSE == gbXSessionLocked)
            {
            nQueryStat = DBAtomQPop(&gxAtomRecord);
            ASSERT_SUCCESS(nQueryStat);

            nQueryStat = DBRecordFlowChar(
                            eMacro, gnAtomRecordID,
                            IMMEDIATE, 
							&gxAtomRecord.nRecordFlow
                            );
            ASSERT_SUCCESS(nQueryStat);

            gxAtomRecord.nVeriSign=gxAtomRecord.nVeriSign ^
                                        gxAtomRecord.nRecordFlow;

            nQueryStat = DBRecordBufferize(&gxAtomRecord);
            ASSERT_SUCCESS(nQueryStat);
            }
        else
	        {
	        return;
	        }
        }

    nQueryStat = DBRecordBufferSize(&gxAtomRecord,
                                 &u16RecordSize);
    ASSERT_SUCCESS(nQueryStat);
    nQueryStat = DBSendRecord((unsigned char*)&gxAtomRecord,
                                  u16RecordSize);

    if ( UNDEF == nQueryStat)
        {
        gbXSessionRetry = TRUE;
        odoDBMacroCommit(TRUE);
        return UNDEF;
        }

    gbXSessionRetry = FALSE; 

    nQueryStat = odoDBRetryConfirmStart();
    ASSERT_SUCCESS(nQueryStat);

	gbXSessionLocked = TRUE; 
    gnRollBConf=0; 

    return;
    }

void 
odoDBMacroRecordRetry
    (
    void
    )
    {
    unsigned short u16RecordSize;
    int nQueryStat;

	nQueryStat = UNDEF;

    ASSERT(gbXSessionEnabled);

	if(TRUE == gbXSessionMaster)
		{
		nQueryStat = DBSendFlowRecord(eSession);
		ASSERT_SUCCESS(nQueryStat);

                nQueryStat = odoDBRetryConfirmStart();
                ASSERT_SUCCESS(nQueryStat);
		
		return;
		}

    if(FALSE == gbXSessionLocked)
        {
        return;
        }

    if ( (gnRollBConf < DB_MAX_RollBConf))
        {
        nQueryStat = DBRecordBufferSize(&gxAtomRecord,
                                 &u16RecordSize);
        ASSERT_SUCCESS(nQueryStat);

        nQueryStat = DBSendRecord((unsigned char*)&gxAtomRecord,
                                  u16RecordSize);
        ASSERT_SUCCESS(nQueryStat);

        ++gnRollBConf;

        nQueryStat = odoDBRetryConfirmStart();
        ASSERT_SUCCESS(nQueryStat);

        }
    else
        {
        gnRollBConf = 0;
        gbXSessionEnabled = FALSE;
        }

    return;
    }

void 
odoDBMacroRecordCommit
    (
    unsigned char   *pnMacro,
    unsigned short  u16Size
    )
    {
    int nQueryStat;

	nQueryStat = UNDEF;

    ASSERT(gbXSessionEnabled);
    ASSERT(pnMacro);
    odoDB_FAIL_ON_SIZE_EXCEEDS(u16Size, DB_MAXLEN);

    gxRecordTemp.SOP[0]=64;
    gxRecordTemp.SOP[1]=64;
    gxRecordTemp.nMacroSize=(unsigned char)u16Size;

    nQueryStat = DBRecordFlowChar(eMacro,
                                 0,
                                 IMMEDIATE,
                                 &gxRecordTemp.nRecordFlow);
    ASSERT_SUCCESS(nQueryStat);

    nQueryStat= odoMemcpy8(gxRecordTemp.anMacro, pnMacro, u16Size);
    ASSERT_SUCCESS(nQueryStat);

    DBRecordVeriSignCompute(pnMacro,
                                 u16Size,
                                 &gxRecordTemp.nVeriSign);

    gxRecordTemp.nVeriSign = gxRecordTemp.nVeriSign ^
                                gxRecordTemp.nMacroSize;

    gxRecordTemp.nVeriSign = gxRecordTemp.nVeriSign ^
                                gxRecordTemp.nRecordFlow;

	nQueryStat = DBAtomQCommit(&gxRecordTemp);
    ASSERT_SUCCESS(nQueryStat);

    return;
    }

void 
DBSendFlowRecord
    (
    DBRecordType eRequestedType
    )
    {
    int nQueryStat;

	nQueryStat = UNDEF;

    gxRecordFlow.SOP[0] = 64;
    gxRecordFlow.SOP[1] = 64;
    gxRecordFlow.nMacroSize = 0;

    switch(eRequestedType)
        {
        case eForce:
            DBRecordFlowChar(eForce,
                                    IMMEDIATE,
                                    gnBConfupRecordID,
                                    &gxRecordFlow.nRecordFlow);
            break;

        case eForcePrev:
            DBRecordFlowChar(eForce,
                                    IMMEDIATE,
                                    Predecessor(gnBConfupRecordID,
                                        (DB_MAX_Record_ID + 1)),
                                    &gxRecordFlow.nRecordFlow);
            break;

		case eSession:
			DBRecordFlowChar(eSession,
									IMMEDIATE,
									IMMEDIATE,
									&gxRecordFlow.nRecordFlow);
			break;

        default:
            return UNDEF;
        }

    gxRecordFlow.nVeriSign = gxRecordFlow.nMacroSize ^
                                        gxRecordFlow.nRecordFlow;

    nQueryStat = DBSendRecord((unsigned char*)&gxRecordFlow,
                                         DBRecord_SIZE);
    ASSERT_SUCCESS(nQueryStat);

    return;
    }

void 
DBReinit
    (
    void
    )
    {
    gnBConfupRecordID=0;
    gnAtomRecordID=0;
    gnRollBConf=0;

    return;
    }

void 
DBFlowRecordSave
    (
    unsigned char nRecordFlow
    )
    {
    DBRecordType  eRecordType;
    void       nQueryStat;
    unsigned char     nRecordID;

	eRecordType = eUnknown;
	nQueryStat = UNDEF;
	nRecordID = 0;

    nQueryStat = DBRecordFlowCharType(nRecordFlow,
                                    &eRecordType);
    ASSERT_SUCCESS(nQueryStat);

    if (eForce == eRecordType)
        {
        if (FALSE == gbXSessionLocked)
            {
            return;
            }

        nQueryStat = DBRecordFlowCharMST(nRecordFlow, &nRecordID);
        ASSERT_SUCCESS(nQueryStat);

        if (nRecordID == gnAtomRecordID)
            {
            odoDBDelegateValidConf();
            }
		else
			{
			return;
			}
        }
	else if(eSession == eRecordType)
		{
		odoDBDelegateSessionRecord();
		}
	else
		{
		return UNDEF;
		}

    return;
    }


/**
 * BASELINE HISTORY
 *
 * \version 000,20090706,sod  initial version.
 * \version 001,20090901,sod  Restructured
 */




